<?php

namespace app\model;

use Laf\Log;
use mon\orm\Model;
use mon\util\Instance;
use mon\orm\exception\DbException;

/**
 * 配置管理模型
 *
 * Class Setting
 * @copyright 2021-03-24 mon-console
 * @version 1.0.0
 */
class SettingModel extends Model
{
    use Instance;

    /**
     * 操作表
     *
     * @var string
     */
    protected $table = 'setting';

    /**
     * 新增自动写入字段
     *
     * @var array
     */
    protected $insert = ['create_time', 'update_time'];

    /**
     * 更新自动写入字段
     *
     * @var array
     */
    protected $update = ['update_time'];

    /**
     * 自动完成组别标题
     *
     * @var array
     */
    protected $append = ['title'];

    /**
     * 缓存的配置信息
     *
     * @var array
     */
    protected $cacheData = [];

    /**
     * 组别名称配置项key值
     *
     * @var string
     */
    public $groupTitleKey = 'group_title';

    /**
     * 组别名称配置项名称
     *
     * @var string
     */
    public $groupTitleName = '配置组别名称';

    /**
     * 组别索引对应标题
     *
     * @var array
     */
    public $groupTitle = [];

    /**
     * 构造方法
     */
    public function __construct()
    {
        $this->groupTitle = $this->getConfig('group_title');
    }

    /**
     * 查询信息
     *
     * @param array $where where条件
     * @param mixed $field 查询字段
     * @return mixed
     */
    public function getInfo(array $where, $field = '*')
    {
        $info = $this->where($where)->field($field)->find();
        if (!$info) {
            $this->error = '记录信息不存在';
            return false;
        }

        return $info;
    }

    /**
     * 获取配置组别
     *
     * @param integer $where where条件
     * @return array
     */
    public function getGroup($where = ['status' => 1])
    {
        return $this->where($where)->group('group')->field('group')->order('id', 'desc')->all();
    }

    /**
     * 获取类别配置信息
     *
     * @param string $group 组别名称
     * @param boolean $make 是否进行格式转换
     * @param boolean $cache 是否允许从缓存中获取数据
     * @return array
     */
    public function getConfig($group, $make = true, $cache = true)
    {
        if ($cache && isset($this->cacheData[$group])) {
            $config = $this->cacheData[$group];
        } else {
            $config = $this->where('group', $group)->where('status', 1)->select();
            $this->cacheData[$group] = $config;
        }

        return $make ? $this->makeConfig($config) : $config;
    }

    /**
     * 新增配置
     *
     * @param array $option 操作参数
     * @return boolean
     */
    public function add(array $option)
    {
        // 校验数据
        $check = $this->validate()->data($option)->rule([
            'group'     => ['required', 'str', 'account'],
            'index'     => ['required', 'str', 'account'],
            'value'     => ['str'],
            'remark'    => ['str']
        ])->message([
            'group'     => '请输入合法的组别索引名称',
            'index'     => '请输入合法的配置索引名称',
            'value'     => '请输入合法的配置值',
            'remark'    => '请输入合法的备注信息'
        ])->check();
        if ($check !== true) {
            $this->error = $this->validate()->getError();
            return false;
        }
        // 校验配置节点是否已存在
        $check = $this->where('group', $option['group'])->where('index', $option['index'])->find();
        if ($check) {
            $this->error = '配置节点已存在';
            return false;
        }

        $info = [
            'group'     => $option['group'],
            'index'     => $option['index'],
            'value'     => $option['value'],
            'remark'    => isset($option['remark']) ? $option['remark'] : '',
        ];

        $this->startTrans();
        try {
            $res = $this->save($info);
            Log::instance()->oss(__FILE__, __LINE__, 'add config', 'sql');
            if (!$res) {
                $this->rollback();
                $this->error = '增加配置节点失败';
                return false;
            }

            // 记录操作日志
            $record = AdminLogModel::instance()->record(['action' => '新增配置', 'content' => json_encode($info, JSON_UNESCAPED_UNICODE)]);
            if (!$record) {
                $this->rollback();
                $this->error = '记录操作日志失败';
                return false;
            }

            $this->commit();
            return true;
        } catch (DbException $e) {
            $this->rollback();
            $this->error = '新增配置异常';
            Log::instance()->oss(__FILE__, __LINE__, 'add config exception, msg => ' . $e->getMessage(), 'error');
            return false;
        }
    }

    /**
     * 编辑
     *
     * @param  array  $option [description]
     * @return boolean
     */
    public function edit(array $option)
    {
        // 校验数据
        $check = $this->validate()->data($option)->rule([
            'id'        => ['required', 'int', 'min:1'],
            'value'     => ['str'],
            'remark'    => ['str']
        ])->message([
            'id'        => '参数错误',
            'value'     => '请输入合法的配置值',
            'remark'    => '请输入合法的备注信息'
        ])->check();
        if ($check !== true) {
            $this->error = $this->validate()->getError();
            return false;
        }

        $check = $this->where('id', $option['id'])->find();
        if (!$check) {
            $this->error = '配置节点不存在';
            return false;
        }

        // 更新配置信息
        $info = [
            'value'     => $option['value'],
            'remark'    => $option['remark']
        ];

        $this->startTrans();
        try {
            Log::instance()->oss(__FILE__, __LINE__, 'modify config', 'sql');
            $res = $this->save($info, ['id' => $option['id']]);
            if (!$res) {
                $this->rollback();
                $this->error = '编辑配置节点失败';
                return false;
            }

            // 记录操作日志
            $record = AdminLogModel::instance()->record(['action' => '编辑配置', 'content' => json_encode($info, JSON_UNESCAPED_UNICODE)]);
            if (!$record) {
                $this->rollback();
                $this->error = '记录操作日志失败';
                return false;
            }

            $this->commit();
            return true;
        } catch (DbException $e) {
            $this->rollback();
            $this->error = '编辑配置异常';
            Log::instance()->oss(__FILE__, __LINE__, 'edit config exception, msg => ' . $e->getMessage(), 'error');
            return false;
        }
    }

    /**
     * 编译转换配置信息列表
     *
     * @param  array $config 配置信息
     * @return array
     */
    protected function makeConfig($config)
    {
        $res = [];
        foreach ($config as $v) {
            $res[$v['index']] = $v['value'];
        }
        return $res;
    }

    /**
     * 转换获取组别标题
     *
     * @param mixed $val
     * @param mixed $data
     * @return string
     */
    protected function getTitleAttr($val, $data)
    {
        if (!isset($data['group'])) {
            return '';
        }
        if ($data['group'] == $this->groupTitleKey) {
            return $this->groupTitleName;
        }
        if (!isset($this->groupTitle[$data['group']])) {
            return $data['group'];
        }
        return $this->groupTitle[$data['group']];
    }

    /**
     * 自动完成create_time字段
     * 
     * @param mixed $val 默认值
     * @param array  $row 列值
     * @return string
     */
    protected function setCreateTimeAttr($val)
    {
        return time();
    }

    /**
     * 自动完成update_time字段
     * 
     * @param mixed $val 默认值
     * @param array  $row 列值
     * @return string
     */
    protected function setUpdateTimeAttr($val)
    {
        return time();
    }
}
